package com.gtenacg.cartoonservice.common.aspect;

import com.gtenacg.cartoonservice.common.annotation.CheckToken;
import com.gtenacg.cartoonservice.common.Result;
import com.gtenacg.cartoonservice.compent.JwtProperties;
import com.gtenacg.cartoonservice.util.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class CheckTokenAspect {

    @Pointcut("@annotation(com.gtenacg.cartoonservice.common.annotation.CheckToken)")
    public void CheckTokenOnMethod() {}
    @Pointcut("within(@com.gtenacg.cartoonservice.common.annotation.CheckToken *)")
    public void CheckTokenOnClass() {}

    @Pointcut("CheckTokenOnMethod() || CheckTokenOnClass()")
    public void pointcut() {}

    final JwtUtil jwtUtil;
    final JwtProperties jwtProperties;

    @Around("pointcut()")
    public Object checkTokenSubject(ProceedingJoinPoint joinPoint) throws Throwable {
        // 处理请求
        ServletRequestAttributes requestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        if (requestAttributes == null) {
            log.error("requestAttributes is null: {}", signature.getName());
            return new Result<Void>(HttpStatus.BAD_REQUEST.value(), "请求无效？？？", null);
        }

        // 身份验证
        HttpServletRequest request = requestAttributes.getRequest();
        String requestInfo = request.getMethod() + " " + request.getServletPath();
        try {

            String token = request.getHeader("token");
            if (token == null) {
                throw new RuntimeException("没有携带token");
            }
            Claims claims = jwtUtil.parseToken(token);

            // 获取注解实例
            CheckToken checkToken = signature.getMethod().getAnnotation(CheckToken.class);
            if (checkToken == null) {
                checkToken = signature.getMethod().getDeclaringClass().getAnnotation(CheckToken.class);
            }
            // 检查token的subject是否符合注解标识一致
            if (!claims.getSubject().equals(jwtProperties.getSubjectMap().get(checkToken.subjectKey()))) {
                log.error("token 应用场景不符合, 预计场景：{}, token适用场景：{}",
                        checkToken.subjectKey(), claims.getSubject() );
                throw new RuntimeException("token 应用场景不符合");
            }
            log.warn("管理员ID: {}, 访问敏感接口: {}", claims.get("id"), requestInfo);

        } catch (RuntimeException e) {
            // 统一拦截
            log.warn("敏感接口 {} 被意外访问, 已拦截", requestInfo);
            return new Result<Void>(HttpStatus.UNAUTHORIZED.value(), "权限不足", null);
        }

        // 继续执行
        return joinPoint.proceed();
    }

}
